package main

import (
	"bytes"
	"github.com/gorilla/websocket"
	"github.com/hpcloud/tail"
	"log"
	"net/http"
	"strings"
)

type Client struct {
	socket *websocket.Conn
	send   chan []byte
}

type Broadcaster struct {
	clients    map[string]*Client
	broadcast  chan string
	register   chan *Client
	unregister chan *Client
	executeRes chan string
}
type ServiceInfo struct {
	ServiceName string
	FilePath    string
	Lines       int
}
type WsInfo struct {
	ServiceInfo ServiceInfo
	Broadcaster *Broadcaster
}

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

var serviceMap = make(map[string]WsInfo)

func newBroadcaster() *Broadcaster {
	return &Broadcaster{
		broadcast:  make(chan string),
		register:   make(chan *Client),
		unregister: make(chan *Client),
		clients:    make(map[string]*Client),
		executeRes: make(chan string),
	}
}
func (b *Broadcaster) tailFile(filepath string) {
	t, err := tail.TailFile(
		filepath,
		tail.Config{Follow: true, Location: &tail.SeekInfo{Offset: 0, Whence: 2}},
	)
	if err != nil {
		log.Fatalf("tail file err: %v", err)
	}
	allStr := make([]string, 0)
	for line := range t.Lines {
		if line.Text != "" {
			allStr = append(allStr, line.Text)
			b.broadcast <- line.Text + "\n"
		}
	}
	allBytes := []byte(strings.Join(allStr, ""))
	if bytes.Contains(allBytes, []byte("ERROR")) {
		b.executeRes <- "ERROR"
	} else if bytes.Contains(allBytes, []byte("项目启动成功")) {
		b.executeRes <- "项目启动成功"
	} else {
		b.executeRes <- "项目启动中"
	}
}

func (b *Broadcaster) run(serviceName string) {
	for {
		select {
		case client := <-b.register:
			b.clients[serviceName] = client
		case client := <-b.unregister:
			if _, ok := b.clients[serviceName]; ok {
				delete(b.clients, serviceName)
				close(client.send)
			}
		case message := <-b.broadcast:
			b.clients[serviceName].send <- []byte(message)
		case res := <-b.executeRes:
			b.clients[serviceName].send <- []byte(res)
		}
	}
}

func (b *Broadcaster) initialRead(client *Client, filePath string, n int) {
	// Send last n lines from file to the client
	lines, err := readLastNLines(filePath, n)
	if err != nil {
		log.Println(err)
		return
	}
	client.send <- []byte(strings.Join(lines, "\n"))
}
